#include "bitstream"

bitstream::bitstream() {
	charbuf = 0;
	bitcount = 0;
}

ibitstream::ibitstream() {}

ibitstream::ibitstream(std::istream *newBaseStream) {
	baseStream = newBaseStream;
}

int ibitstream::get() {
	int ret = 0;
	if(!bitcount) {
		if((ret = baseStream->get())!=EOF) charbuf = ret;
		bitcount = UCHAR_BIT;
	}
	if(ret != EOF) {
		ret = (bool)(charbuf & UCHAR_MAXBIT);
		charbuf <<= 1;
		bitcount--;
	}
	return ret;
}

int ibitstream::getc() {
	int ret = 0, dummy = 0;
	for(uchar i = 0; i < UCHAR_BIT; i++) {
		if((dummy = get()) == EOF) return EOF;
		ret <<= 1;
		ret |= dummy;
	}
	return ret;
}

unsigned ibitstream::read(char* buf, unsigned size) {
	unsigned readsize = 0;
	for(int dummy; (readsize < size); readsize++) {
		if((dummy = getc()) == EOF) break;
		buf[readsize] = dummy;
	}
	return readsize;
}

obitstream::obitstream() {}

obitstream::obitstream(std::ostream *newBaseStream) {
	baseStream = newBaseStream;
}

void obitstream::put(bool in) {
	charbuf = (charbuf << 1) | in;
	if(++bitcount == UCHAR_BIT) pad();
}

void obitstream::putc(uchar c) {
	for(uchar i = 0; i < UCHAR_BIT; i++) {
		put(c & UCHAR_MAXBIT);
		c <<= 1;
	}
}

void obitstream::write(char* buf, unsigned size) {
	while(size--) putc(*(buf++));
}

void obitstream::pad(bool padding) {
	if(bitcount) {
		if(bitcount < UCHAR_BIT) {
			uchar diff = UCHAR_BIT - bitcount;
			charbuf <<= (diff);
			if(padding) charbuf |= (UCHAR_MAX >> diff);
		}
		baseStream->put(charbuf);
		bitcount = 0;
	}
}

